﻿/**
 * Licensed to Open-Ones Group under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Open-Ones Group licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a
 * copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using InTheHand.Net;
using InTheHand.Net.Sockets;
using InTheHand.Net.Bluetooth;
namespace BluetoothServer
{
    class BluetoothServerSocket
    {
        private Guid service = new Guid("{7A51FDC2-FDDF-4c9b-AFFC-98BCD91BF93B}");
        private BluetoothListener btListener;
        private Boolean blnListening = true;
        private StreamWriter writer = null;
        private StreamReader reader = null;
        private BluetoothClient btClient = null;

        public BluetoothServerSocket()
        {
            btListener = new BluetoothListener(service);
        }

        /// <summary>
        /// turn on/off bluetooth device inorder for others device may discover it.
        /// </summary>
        /// <param name="available">
        /// Action that user want to perform
        /// available = true : turn on
        /// available = false : turn off
        /// </param>
        /// <returns>True if succeed, false if error occurs.</returns>
        public Boolean SetAvailble(Boolean available)
        {
            BluetoothRadio blRadio = BluetoothRadio.PrimaryRadio;
            // if user want to turn on Bluetooth
            if (available)
            {
                if (blRadio == null)
                {
                    return false;
                }
                // Set discoverable mode so that other device can discover bluetooth on this PC
                blRadio.Mode = RadioMode.Discoverable;
                return true;
            }
            else
            {
                // turn off bluetooth
                if (blRadio == null)
                {
                    return false;
                }
                blRadio.Mode = RadioMode.PowerOff;
                return true;
            }
        }

        /// <summary>
        /// Set Pin code for pairing device
        /// </summary>
        /// <param name="pin">PIN code.</param>
        public void SetPin(String pin)
        {
            BluetoothAddress remoteAddress = btClient.RemoteEndPoint.Address;
            btClient.SetPin(remoteAddress, pin);
        }

        /// <summary>
        ///check if paired device is connected
        /// </summary>
        /// <returns>true if connected, otherwise, return false
        /// </returns>
        public Boolean IsConnected()
        {
            if (btClient != null &&
                btClient.Connected &&
                reader != null &&
                writer != null)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Listen for connection from others device
        /// and create stream to send and receive data to/from client
        /// </summary>
        /// <returns>true if listen successfully, false if an exception thrown
        /// </returns>
        public Boolean Listen()
        {
            try
            {
                btListener.Start();     // Start waiting for connection
                // Accept connection from client
                btClient = btListener.AcceptBluetoothClient();
                // Only accept 1 connection and then Stop listen.
                btListener.Stop();
                // Get Stream writer and stream reader
                writer = new StreamWriter(btClient.GetStream());
                reader = new StreamReader(btClient.GetStream());
                return true;
            }
            catch(Exception ex)
            {
                // if exception occur, close socket and opened stream
                btListener.Stop();
                if (btClient != null)
                {
                    btClient.Close();
                    btClient = null;
                }
                writer = null;
                reader = null;
                return false;
            }
        }

        /// <summary>
        /// Close Client bluetooth socket an
        /// </summary>
        public void Close()
        {
            reader.Close();     // Close Stream reader
            writer.Close();     // Close Stream writer
            btClient.Close();   // Close bluetooth socket
        }
        
        /// <summary>
        /// Read data sent by client.
        /// </summary>
        /// <returns>
        /// Read data string.
        /// </returns>
        public String Read()
        {
            if (IsConnected())
            {
                // char hold size of received data
                char[] size = new char[1];
                // char array hold data content.
                char[] receivedData;
                try
                {
                    reader.Read(size,0,1);
                    receivedData = new char[size[0]];
                    reader.Read(receivedData, 0, size[0]);
                    return new String(receivedData);
                }
                catch (Exception e)
                {
                    // if exception occurs
                    return null;
                }
            }
            else
            {
                // if connection does'nt exist
                return null; 
            }
        }

        /// <summary>
        /// Sent data to client
        /// </summary>
        /// <param name="message">
        /// String data to be sent.
        /// </param>
        /// <returns>
        /// Return 1 if success, 0 if errors occur, -1 if connection has not been established
        /// </returns>
        public int Write(String message)
        {
            if (IsConnected())
            {
                try
                {
                    writer.Write(message);
                    return 1;
                }
                catch (Exception e)
                {
                    //send data error
                    return 0;
                }
            }
            else
            {
                // not connected yet
                return -1;
            }
        } 
    }
}
